package top.xcxdl.rural.controller.admin;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import lombok.extern.log4j.Log4j2;
import top.xcxdl.rural.common.Res;
import top.xcxdl.rural.config.jwtconfig.JwtConfigProperties;
import top.xcxdl.rural.config.initexception.BusinessException;
import top.xcxdl.rural.config.initexception.ErrorEnum;
import top.xcxdl.rural.entity.BackAdmin;
import top.xcxdl.rural.entity.BackAuthGroup;
import top.xcxdl.rural.entity.BackAuthGroupRule;
import top.xcxdl.rural.entity.BackAuthRule;
import top.xcxdl.rural.service.IBackAdminService;
import top.xcxdl.rural.service.IBackAuthGroupRuleService;
import top.xcxdl.rural.service.IBackAuthGroupService;
import top.xcxdl.rural.service.IBackAuthRuleService;
import top.xcxdl.rural.utils.JWTUtils;
import top.xcxdl.rural.utils.JwtInterceptor;
import top.xcxdl.rural.utils.RedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Ding
 * @create 2022/1/27 12:30
 */
@Api("后台管理员控制器")
@Log4j2
@RestController
@CrossOrigin
@RequestMapping("/admin/adminUser")
public class AdminUserController {

    @Resource
    private IBackAdminService service;
    @Resource
    private IBackAuthGroupService groupService;
    @Resource
    private IBackAuthRuleService ruleService;
    @Resource
    private IBackAuthGroupRuleService groupRuleService;
    @Resource
    private JwtConfigProperties jwtConfigProperties;

    private static final String SUPER_ADMIN = "SUPER_ADMIN";

    /**
     * 后台管理员登录
     *
     * @param data 传回来的表单
     * @return Res
     */
    @ResponseBody
    @ApiOperation("管理员登录")
    @PostMapping("/login")
    public Res<Object> adminUserLogin(@RequestBody JSONObject data) {
        String username = String.valueOf(data.get("username"));
        String password = String.valueOf(data.get("password"));
        BackAdmin admin = service.toLogin(username, password);
        if (admin != null) {
            if (admin.getAStatus() == 1) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("token", JWTUtils.sign(String.valueOf(admin.getAId()), "1", admin.getAUsername(), jwtConfigProperties));
                log.info("管理员{}（ID为{}）登录后台成功", admin.getAUsername(), admin.getAId());
                return Res.success(jsonObject, "登录成功");
            } else {
                // 用户被禁用
                log.info("管理员{}（ID为{}）登录失败，原因为账号已被禁用", admin.getAUsername(), admin.getAId());
                return Res.error(ErrorEnum.LOGIN_ACCOUNT_DISABLED);
            }
        } else {
            // 用户名或密码错误
            return Res.error(ErrorEnum.LOGIN_INVALID);
        }
    }

    /**
     * 获取管理员信息
     *
     * @return Res
     */
    @ResponseBody
    @ApiOperation("获取管理员信息")
    @GetMapping("/getUserInfo")
    public Res<JSONObject> getUserInfo() {
        JSONObject jsonTemp = new JSONObject();
        Integer id = JWTUtils.getAuthorId();
        BackAdmin admin = service.getAdminUserById(id);
        jsonTemp.put("userInfo", admin);
        jsonTemp.put("username", admin.getAUsername());
        jsonTemp.put("avatar", admin.getAvatarUrl());
        jsonTemp.put("roles", new String[]{"Admin"});
        jsonTemp.put("permissions", new String[]{"read:system", "write:system", "delete:system"});
        return Res.success(jsonTemp);
    }

    /**
     * 获取菜单权限
     *
     * @return Res
     */
    @ApiOperation("获取菜单权限")
    @ResponseBody
    @GetMapping("/getRuleRouters")
    public Res<JSONObject> getRuleRouters() {
        JSONObject jsonTemp = new JSONObject();
        //根据token取id，进阶获取用户角色组id
        Integer aId = JWTUtils.getAuthorId();
        Integer groupId = service.getById(aId).getAGroupId();
        //根据角色id获取角色权限
        BackAuthGroup group = groupService.getById(groupId);
        List<BackAuthRule> rules = new ArrayList<>();
        if ((SUPER_ADMIN).equals(group.getRole())) {
            //最高权限管理员
            rules = ruleService.getAllRules(null, group.getRole());
        } else {
            //普通权限管理员
            //获取联表信息
            String ids = groupRuleService.getIdsStringByGroupId(groupId);
            rules = ruleService.getAllRules(ids, group.getRole());
        }
        jsonTemp.put("list", rules);
        return Res.success(jsonTemp);
    }

    /**
     * 登出
     *
     * @return 登出
     */
    @ApiOperation("退出登录")
    @ResponseBody
    @GetMapping("/logout")
    public Res<JSONObject> logout() {
        return Res.success("退出成功");
    }

    /**
     * 加载管理员列表
     *
     * @param pageNo   页码
     * @param pageSize 每页装载量
     * @return res
     */
    @ApiOperation("获取管理员列表")
    @ResponseBody
    @GetMapping("/getList")
    public Res<JSONObject> getList(
            @RequestParam("page_no") Integer pageNo,
            @RequestParam("page_size") Integer pageSize,
            @RequestParam(name = "title", defaultValue = "") String title) {
        JSONObject jsonTemp = new JSONObject();
        Integer aId = JWTUtils.getAuthorId();
        Integer groupId = service.getById(aId).getAGroupId();
        //根据角色id获取角色权限
        BackAuthGroup group = groupService.getById(groupId);
        if (SUPER_ADMIN.equals(group.getRole())) {
            //最高权限，必然获取
            PageInfo<BackAdmin> list = service.getList(pageNo, pageSize, title);
            jsonTemp.put("list", list.getList());
            jsonTemp.put("total", list.getTotal());
        } else {
            //普通权限，必然不能拥有系统管理的权限-防止篡位
            return Res.error(ErrorEnum.NO_AUTH);
        }
        return Res.success(jsonTemp);
    }

    /**
     * 重置密码为 123456
     *
     * @param bean pojo实体类
     * @return res
     */
    @ApiOperation("重置密码")
    @PostMapping("/resetPassword")
    @ResponseBody
    public JSONObject resetPassword(@RequestBody BackAdmin bean) {
        JSONObject jsonObject = new JSONObject();
        bean.setAPassword("123456");
        service.doEdit(bean);
        jsonObject.put("code", 200);
        jsonObject.put("msg", "重置成功！");
        return jsonObject;
    }

    /**
     * 添加 or 编辑 管理员
     *
     * @param bean pojo实体类
     * @return res
     */
    @ApiOperation("添加 or 编辑 管理员")
    @PostMapping("/doEdit")
    @ResponseBody
    public Res<JSONObject> doEdit(@RequestBody BackAdmin bean) {
        //编辑对象的条数
        int editNum = 0;
        //编辑对象是否是最后一个超级管理员
        boolean isLastSuperAdmin = false;
        //编辑对象是否是登录者
        boolean isLoginAdmin = false;
        //结果判定值
        int ret = 0;
        //是否是超级管理员
        boolean isSuperAdmin = SUPER_ADMIN.equals(groupService.getGroupById(service.getById(JWTUtils.getAuthorId()).getAGroupId()).getRole());
        //防止低权限身份入侵
        if (!isSuperAdmin) {
            //需要更高权限
            return Res.error(ErrorEnum.HIGHEST_AUTH);
        }
        //判断是添加还是编辑管理员
        if (bean.getAId() == null) {
            if (service.getByUsername(bean.getAUsername()) > 0) {
                //存在用户，驳回
                return Res.error(ErrorEnum.REGISTERED_ACCOUNT_EXISTS);
            }
        } else {
            judgeDownGrade(bean);
        }

        /*
          没有被拦截
          走添加/编辑方法
         */
        boolean isAdd = bean.getAId() == null;
        editNum += service.doEdit(bean);
        if (editNum > 0) {
            return Res.success(isAdd ? "添加成功" : "编辑成功");
        } else {
            return Res.error();
        }
    }

    /**
     * 判定降权操作
     * 判断是否即将进行降权，且是否达到不可降权条件，如是则抛出异常，反之该方法直接跃过
     *
     * @param bean 管理员实体
     */
    void judgeDownGrade(BackAdmin bean) {
        //编辑对象是否是 超级管理员
        boolean isLastSuperAdmin = groupService.getSuperAdminNum() <= 1;
        //编辑对象是否是 登录者本人
        boolean isLoginAdmin = bean.getAId().equals(JWTUtils.getAuthorId());
        //编辑操作是否是降级操作（编辑的实体中权限不是SUPER_ADMIN 并且 编辑对象之前的权限是SUPER_ADMIN则说明 是降级操作，返回true）
        boolean isDownGrade = !SUPER_ADMIN.equals(groupService.getGroupById(bean.getAGroupId()).getRole())
                && SUPER_ADMIN.equals(groupService.getGroupById(service.getById(bean.getAId()).getAGroupId()).getRole());
        //判定是否不允许操作（只要是最后一个超管或登录者本人就是超管，并且是降权操作 就返回true即不允许）
        boolean isNotAllow = (isLastSuperAdmin || isLoginAdmin) && isDownGrade;

        if (isNotAllow) {
            //说明是降权操作，但是不允许降权，下面判断失败类型：
            if (isLastSuperAdmin && isLoginAdmin) {
                //拒绝原因为：为自己账号降权 且 此时仅剩一个超级管理员
                throw new BusinessException(ErrorEnum.PERMISSION_FAILED_ALL);
            }
            if (isLoginAdmin) {
                //拒绝原因为：不能为自己降权
                throw new BusinessException(ErrorEnum.PERMISSION_FAILED_YOURSELF);
            }
            //拒绝原因为：您不能为唯一的超级管理员降低权限
            throw new BusinessException(ErrorEnum.PERMISSION_FAILED_LAST_SUPER);
        }
    }

    /**
     * 删除管理员
     *
     * @param data json类型的ids-需要处理成数组和list
     * @return res
     */
    @ApiOperation("删除管理员")
    @ResponseBody
    @PostMapping("/doDelete")
    public Res<JSONObject> doDelete(@RequestBody JSONObject data) {
        //处理前端数据
        String[] idsStr = String.valueOf(data.get("ids")).split(",");
        List<Integer> ids = new ArrayList<>();
        for (String s : idsStr) {
            ids.add(Integer.parseInt(s));
        }
        //遍历，确认其身份不是SUPER_ADMIN，否则return
        int beforeIdsSize = ids.size();
        for (int i = 0; i < ids.size(); i++) {
            if (SUPER_ADMIN.equals(groupService.getGroupById(service.getById(ids.get(i)).getAGroupId()).getRole())) {
                ids.remove(i--);
            }
        }
        if (ids.size() < beforeIdsSize) {
            return Res.error("选择中含有" + (beforeIdsSize - ids.size()) + "个超级管理员，请取消相应的勾选");
        }
        //初始化
        int delNum = 0;
        //执行
        delNum += service.doDeleteBy(ids);
        if (delNum >= ids.size()) {
            return Res.success("已删除" + delNum + "个管理员");
        } else if (delNum > 0) {
            return Res.success("部分删除成功，" + delNum + "/" + ids.size());
        } else {
            return Res.error();
        }
    }

    /**
     * 禁用 or 启用 管理员
     *
     * @param bean pojo实体类
     * @return res
     */
    @ApiOperation("禁用/启用管理员")
    @PostMapping("/changeStatus")
    @ResponseBody
    public Res<JSONObject> changeStatus(@RequestBody BackAdmin bean) {
        JSONObject jsonObject = new JSONObject();
        if (service.doEdit(bean) > 0) {
            return Res.success(bean.getAStatus() == 1 ? "启用成功！" : "禁用成功！");
        } else {
            return Res.error();
        }
    }

    /**
     * 添加客服电话
     *
     * @param data 客服电话
     * @return res
     */
    @ApiOperation("修改客服电话")
    @PostMapping("/changeService")
    @ResponseBody
    public Res<JSONObject> changeService(@RequestBody JSONObject data) {
        List<String> serviceList = (List<String>) data.get("service_tels");
        RedisUtils.changeService(serviceList);
        return Res.success("已更新电话客服");
    }

    /**
     * 查询客服电话
     *
     * @return res
     */
    @ApiOperation("查询客服电话")
    @GetMapping("/getService")
    @ResponseBody
    public Res<JSONObject> getService() {
        JSONObject jsonTemp = new JSONObject();
        jsonTemp.put("list", RedisUtils.getService());
        return Res.success(jsonTemp);
    }
}
